/*
 * PanelLed.cpp
 *
 *  Created on: Dec 23, 2011
 *      Author: kylintse
 */
#include <fcntl.h>
#include <sys/ioctl.h>

#include "PanelLed.h"
#include "wdg_led.h"
#include "gdata.h"

#define WINK_ACCURACY	100

const int led_id[]=
{
		LED_01,
		LED_02,
		LED_03,
		LED_04,
		LED_05,
		LED_06,
		LED_07,
		LED_08,
		LED_09,
		LED_10,
		LED_11,
		LED_12,
		LED_13,
		LED_14,
		LED_15,
		LED_16,
		LED_17,
		LED_18,
		LED_19,
		LED_20,
		LED_21,
		LED_22,
		LED_23,
		LED_24,
};

const int led_DC=LED_01;
const int led_AC1=LED_02;
const int led_AC2=LED_03;
const int led_Rs485[]=
{
		LED_04,
		LED_05,
		LED_06,
		LED_07,
};
const int led_Can[]=
{
		LED_08,
		LED_09
};
const int led_1000M[]={
		LED_10,
		LED_11,
		LED_12,
};
const int led_100M[]={
		LED_13,
		LED_14,
		LED_15,
		LED_16,
		LED_17,
		LED_18,
		LED_19,
		LED_20,
		LED_21,
		LED_22,
//		LED_23,
//		LED_24,
};

const int led_Eth0=LED_23;
const int led_Eth1=LED_24;

const int hirschman_g_port[]=
{

};

const int hirschman_100m_port[]=
{

};

const int moxa_g_port[]=
{
		8,9,10
};

const int moxa_100m_port[]=
{
		1,2,3,4,5,6,7
};

////////////////////////////////////////////////////////////////////////////////
// class SwitchStauts
SwitchStatus::SwitchStatus(int ledFd,QObject* parent/*=0*/)
	: kthread(parent),m_ledFd(ledFd)
{
	m_switchCheckCount=0;
	m_switchCheckFreq=2;

	if(gswitchType=="Hirschman")
	{
		m_port_g=hirschman_g_port;
		m_port_100m=hirschman_100m_port;
		m_port_g_num=sizeof(hirschman_g_port)/sizeof(int);
		m_port_100m_num=sizeof(hirschman_100m_port)/sizeof(int);
	}
	else if(gswitchType=="Moxa")
	{
		m_port_g=moxa_g_port;
		m_port_100m=moxa_100m_port;
		m_port_g_num=sizeof(moxa_g_port)/sizeof(int);
		m_port_100m_num=sizeof(moxa_100m_port)/sizeof(int);
	}

	m_port_g_status=new int[m_port_g_num];
	m_port_100m_status=new int[m_port_100m_num];
}

SwitchStatus::~SwitchStatus()
{

}

void SwitchStatus::run()
{
	setStarted(true);

	while(true)
	{
		if(needExit())
		{
			break;
		}

//		qWarning()<<"switch status start";
		struct snmp_session session, *ss;
		struct snmp_pdu *pdu;
		struct snmp_pdu *response=NULL;

		oid anOID[MAX_OID_LEN];
		size_t anOID_len = MAX_OID_LEN;

		struct variable_list *vars;
		int status;

	/*	if((m_switchCheckCount++)%m_switchCheckFreq)
			return;*/

		/*
		* Initialize the SNMP library
		*/
		init_snmp("snmpapp");

		/*
		* Initialize a "session" that defines who we're going to talk to
		*/
		snmp_sess_init( &session );                   /* set up defaults */
		session.peername = gswitchAddr.toAscii().data();

		/* set the SNMP version number */
		session.version = SNMP_VERSION_1;

		/* set the SNMPv1 community name used for authentication */
		session.community = (u_char*)"public";
		session.community_len = strlen((char*)(session.community));

		SOCK_STARTUP;

		/*
		* Open the session
		*/
		ss = snmp_open(&session);                     /* establish the session */

		if (!ss) {
			m_switchCheckFreq=40;
	//		setStarted(false);
	//		snmp_perror("ack");
	//		snmp_log(LOG_ERR, "something horrible happened!!!\n");
			continue;
		}

		QString strOid="IF-MIB::ifOperStatus.";
		QString strResult;

		pdu=snmp_pdu_create(SNMP_MSG_GET);

		for(int i=0;i<m_port_g_num;i++)
		{
			anOID_len = MAX_OID_LEN;
			read_objid((strOid+QString::number(m_port_g[i])).toAscii().data(),anOID,&anOID_len);

			snmp_add_null_var(pdu,anOID,anOID_len);
		}

		status=snmp_synch_response(ss,pdu,&response);

		if(status==STAT_SUCCESS&&response->errstat==SNMP_ERR_NOERROR)
		{
			m_switchCheckFreq=2;
			int i;
			for(vars=response->variables,i=0;vars&&i<m_port_g_num;
					vars=vars->next_variable,i++)
			{
				m_port_g_status[i]=*(vars->val.integer);
	//				qWarning()<<i<<":"<<port_g_status[i];
				if(m_port_g_status[i]==1)
				{
					::ioctl(m_ledFd,DPR_WDG_TURN_ON_LED,&(led_1000M[i]));
				}
				else
				{
					::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&(led_1000M[i]));
				}
			}
		}
		else
		{
			m_switchCheckFreq=40;
		}

		if(response)
			snmp_free_pdu(response);

	//	qWarning()<<"100m_port";
		pdu=snmp_pdu_create(SNMP_MSG_GET);

		for(int i=0;i<m_port_100m_num;i++)
		{
			anOID_len = MAX_OID_LEN;
			read_objid((strOid+QString::number(m_port_100m[i])).toAscii().data(),anOID,&anOID_len);

			snmp_add_null_var(pdu,anOID,anOID_len);
		}

		response=NULL;
		status=snmp_synch_response(ss,pdu,&response);

		if(status==STAT_SUCCESS&&response->errstat==SNMP_ERR_NOERROR)
		{
			m_switchCheckFreq=2;
			int i;
			for(vars=response->variables,i=0;vars&&i<m_port_100m_num;
					vars=vars->next_variable,i++)
			{
				m_port_100m_status[i]=*(vars->val.integer);
	//				qWarning()<<i<<":"<<port_100m_status[i];
				if(m_port_100m_status[i]==1)
				{
					::ioctl(m_ledFd,DPR_WDG_TURN_ON_LED,&(led_100M[i]));
				}
				else
				{
					::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&(led_100M[i]));
				}
			}
		}
		else
		{
			m_switchCheckFreq=40;
		}

		if(response)
			snmp_free_pdu(response);

		snmp_close(ss);

		SOCK_CLEANUP;
		msleep(1000);
	}
}

////////////////////////////////////////////////////////////////////////////////
// class PanelLed
PanelLed::PanelLed(QObject* parent/*=0*/)
	: kthread(parent)
{
	m_switchCheckCount=0;
	m_switchCheckFreq=2;
	m_ledNumber=sizeof(led_id)/sizeof(quint8);
	for(quint32 i=0;i<m_ledNumber;i++)
	{
		m_ledWinkers.insert(led_id[i],-1);
	}
}

PanelLed::~PanelLed()
{
}

void PanelLed::run()
{
	/*if(gswitchType=="Hirschman")
	{
		m_port_g=hirschman_g_port;
		m_port_100m=hirschman_100m_port;
		m_port_g_num=sizeof(hirschman_g_port)/sizeof(int);
		m_port_100m_num=sizeof(hirschman_100m_port)/sizeof(int);
	}
	else if(gswitchType=="Moxa")
	{
		m_port_g=moxa_g_port;
		m_port_100m=moxa_100m_port;
		m_port_g_num=sizeof(moxa_g_port)/sizeof(int);
		m_port_100m_num=sizeof(moxa_100m_port)/sizeof(int);
	}

	m_port_g_status=new int[m_port_g_num];
	m_port_100m_status=new int[m_port_100m_num];*/

	m_ledFd=::open("/dev/dpr_wdg",O_RDWR);

	for(quint32 i=0;i<m_ledNumber;i++)
	{
		::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&led_id[i]);
	}

	QTimer* timerLedStatus=new QTimer;
	connect(timerLedStatus,SIGNAL(timeout()),this,SLOT(checkLedStatus()),
			Qt::DirectConnection);

	timerLedStatus->start(WINK_ACCURACY);

	/*QTimer* timerSwitch=new QTimer;
	connect(timerSwitch,SIGNAL(timeout()),this,SLOT(switchStatus()),
			Qt::DirectConnection);

	timerSwitch->start(1000);*/

//	SwitchStatus* thrSwitch=new SwitchStatus(m_ledFd);
//	thrSwitch->start(5000);

	setStarted(true);

	exec();

	::close(m_ledFd);
	setStarted(false);

	timerLedStatus->stop();
	delete timerLedStatus;

//	thrSwitch->exit();
//	thrSwitch->wait(5000);
//	delete thrSwitch;

	/*timerSwitch->stop();
	delete timerSwitch;*/
}

void PanelLed::checkLedStatus()
{
	QMap<int,int>::iterator i=m_ledWinkers.begin();
	while(i!=m_ledWinkers.end())
	{
		if(i.value()>0)
		{
			i.value()-=WINK_ACCURACY;
//			qWarning()<<i.value();
			if(i.value()<=0)
			{
				::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&i.key());
			}
		}
		i++;
	}
}

void PanelLed::switchStatus()
{
//	qWarning()<<"switch status start";
	struct snmp_session session, *ss;
	struct snmp_pdu *pdu;
	struct snmp_pdu *response=NULL;

	oid anOID[MAX_OID_LEN];
	size_t anOID_len = MAX_OID_LEN;

	struct variable_list *vars;
	int status;

/*	if((m_switchCheckCount++)%m_switchCheckFreq)
		return;*/

	/*
	* Initialize the SNMP library
	*/
	init_snmp("snmpapp");

	/*
	* Initialize a "session" that defines who we're going to talk to
	*/
	snmp_sess_init( &session );                   /* set up defaults */
	session.peername = gswitchAddr.toAscii().data();

	/* set the SNMP version number */
	session.version = SNMP_VERSION_1;

	/* set the SNMPv1 community name used for authentication */
	session.community = (u_char*)"public";
	session.community_len = strlen((char*)(session.community));

	SOCK_STARTUP;

	/*
	* Open the session
	*/
	ss = snmp_open(&session);                     /* establish the session */

	if (!ss) {
		m_switchCheckFreq=40;
//		setStarted(false);
//		snmp_perror("ack");
//		snmp_log(LOG_ERR, "something horrible happened!!!\n");
		return;
	}

	QString strOid="IF-MIB::ifOperStatus.";
	QString strResult;

	pdu=snmp_pdu_create(SNMP_MSG_GET);

	for(int i=0;i<m_port_g_num;i++)
	{
		anOID_len = MAX_OID_LEN;
		read_objid((strOid+QString::number(m_port_g[i])).toAscii().data(),anOID,&anOID_len);

		snmp_add_null_var(pdu,anOID,anOID_len);
	}

	status=snmp_synch_response(ss,pdu,&response);

	if(status==STAT_SUCCESS&&response->errstat==SNMP_ERR_NOERROR)
	{
		m_switchCheckFreq=2;
		int i;
		for(vars=response->variables,i=0;vars&&i<m_port_g_num;
				vars=vars->next_variable,i++)
		{
			m_port_g_status[i]=*(vars->val.integer);
//				qWarning()<<i<<":"<<port_g_status[i];
			if(m_port_g_status[i]==1)
			{
				::ioctl(m_ledFd,DPR_WDG_TURN_ON_LED,&(led_1000M[i]));
			}
			else
			{
				::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&(led_1000M[i]));
			}
		}
	}
	else
	{
		m_switchCheckFreq=40;
	}

	if(response)
		snmp_free_pdu(response);

//	qWarning()<<"100m_port";
	pdu=snmp_pdu_create(SNMP_MSG_GET);

	for(int i=0;i<m_port_100m_num;i++)
	{
		anOID_len = MAX_OID_LEN;
		read_objid((strOid+QString::number(m_port_100m[i])).toAscii().data(),anOID,&anOID_len);

		snmp_add_null_var(pdu,anOID,anOID_len);
	}

	response=NULL;
	status=snmp_synch_response(ss,pdu,&response);

	if(status==STAT_SUCCESS&&response->errstat==SNMP_ERR_NOERROR)
	{
		m_switchCheckFreq=2;
		int i;
		for(vars=response->variables,i=0;vars&&i<m_port_100m_num;
				vars=vars->next_variable,i++)
		{
			m_port_100m_status[i]=*(vars->val.integer);
//				qWarning()<<i<<":"<<port_100m_status[i];
			if(m_port_100m_status[i]==1)
			{
				::ioctl(m_ledFd,DPR_WDG_TURN_ON_LED,&(led_100M[i]));
			}
			else
			{
				::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&(led_100M[i]));
			}
		}
	}
	else
	{
		m_switchCheckFreq=40;
	}

	if(response)
		snmp_free_pdu(response);

	snmp_close(ss);

	SOCK_CLEANUP;
//	qWarning()<<"switch status end";
}

void PanelLed::flashLed(int id,quint32 time)
{
	if(!m_ledWinkers.contains(id))
		return;

	::ioctl(m_ledFd,DPR_WDG_TURN_ON_LED,&id);
	m_ledWinkers[id]=time;
}

void PanelLed::turnOffLed(int id)
{
	if(!m_ledWinkers.contains(id))
		return;

	::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&id);
}

void PanelLed::winkLed()
{
	/*QTimer* winker=(QTimer*)sender();

	if(!m_ledWinkers.contains(winker))
		return;

	int ledId=m_ledWinkers.value(winker);

	::ioctl(m_ledFd,DPR_WDG_TURN_OFF_LED,&ledId);*/
}
